﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;

namespace Ylh.Data
{
    public class OQLWhere
    {

        private String[] _selectColumn;
        public String[] SelectColumn
        {
            get { return _selectColumn; }
            set { _selectColumn = value; }
        }

        private String _strWhere;
        public String StrWhere
        {
            get { return _strWhere; }
            set { _strWhere = value; }
        }
        private Dictionary<string, object> _preWhere = new Dictionary<string, object>();
        public Dictionary<string, object> PreWhere
        {
            get { return _preWhere; }
            set { _preWhere = value; }
        }
        private EntityBase CurrEntity;
        private string currFieldName = "";
        private string currParaName = "";
        private int paraIndex;
        private string PropertyName;
        public OQLWhere(EntityBase e)
        {
            this.CurrEntity = e;
            this.CurrEntity.PropertyNameGetting += new EventHandler<PropertyNameGettingEventArgs>(CurrEntity_PropertyGetting);
            paraIndex = 0;
        }
        private void CurrEntity_PropertyGetting(object sender, PropertyNameGettingEventArgs e)
        {
            PropertyName = e.PropertyName;
            currParaName = "@" + e.PropertyName + "_P" + this.paraIndex;
            currFieldName = "[" + e.PropertyName + "]";
            this.paraIndex++;
        }
        /// <summary>
        /// 拼接相关条件
        /// </summary>
        /// <param name="logicType">逻辑运算类型</param>
        /// <param name="field">类型名称</param>
        /// <param name="compareType">比较字符</param>
        /// <param name="Value">字符的值</param>
        /// <returns></returns>
        private OQLWhere SpliceWhere(string logicType, object field, string compareType, object Value)
        {
            if (String.IsNullOrEmpty(compareType))
                throw new Exception("条件中的运算符号不能为空");

            if (String.IsNullOrEmpty(StrWhere)) StrWhere += @" 1=1 ";
            switch (compareType.ToLower())
            {
                case "=":
                case ">=":
                case "<=":
                case "<":
                case "<>":
                    StrWhere += logicType + currFieldName + " " + compareType + " " + currParaName; break;
                case "is":
                    StrWhere += logicType + currFieldName + " " + compareType + " " + currParaName; break;
                case "llike":
                    StrWhere += logicType + currFieldName + " Like " + "'%'+" + currParaName; break;
                case "rlike":
                    StrWhere += logicType + currFieldName + " Like " + currParaName + "+'%'"; break;
                case "alike":
                    StrWhere += logicType + currFieldName + " Like " + "'%'+" + currParaName + "+'%'"; break;
                default:
                    break;
            }
            PreWhere.Add(currParaName, Value);
            return this;
        }
        /// <summary>
        ///  拼接相关条件
        /// </summary>
        /// <param name="logicType">逻辑运算类型,如:AND,OR,IN</param>
        /// <param name="StrWhere">条件子句</param>
        /// <param name="PreWhere">字句中的参数</param>
        /// <returns></returns>
        private OQLWhere SpliceWhere(string logicType, string StrWhere, Dictionary<string, object> PreWhere)
        {

            List<string> likey = new List<string>(PreWhere.Keys);
            String StrKey = String.Empty;
            String NewStrKey = String.Empty;
            String OldStrIndex = String.Empty;
            int ThisPreCount = this.PreWhere.Count;
            for (int i = 0; i < likey.Count; i++)
            {
                StrKey = likey[i];
                OldStrIndex = StrKey.Split(new string[] { "_P" }, StringSplitOptions.RemoveEmptyEntries)[1];
                NewStrKey = StrKey.Replace(OldStrIndex, ThisPreCount.ToString());
                StrWhere = StrWhere.Replace(StrKey, NewStrKey);
                this.PreWhere.Add(NewStrKey, PreWhere[likey[i]]);
                ThisPreCount++;
            }
            this.StrWhere += " " + logicType + "  (" + StrWhere + ")";
            return this;
        }

        public OQLWhere AND(object field, string compareType, object Value)
        {
            return SpliceWhere(" AND ", field, compareType, Value);
        }

        public OQLWhere AND(OQLWhere where)
        {
            return SpliceWhere(" AND ", where.StrWhere, where.PreWhere);
        }

        public OQLWhere OR(object field, string compareType, object Value)
        {
            return SpliceWhere(" OR ", field, compareType, Value);
        }

        public OQLWhere OR(OQLWhere where)
        {
            return SpliceWhere(" OR ", where.StrWhere, where.PreWhere);
        }

        public OQLWhere IN(object field, string logicType, object[] Value)
        {
            return SpliceWhere_IN(" IN ", field, logicType, Value);
        }

        private OQLWhere SpliceWhere_IN(string CompareType, object field, string logicType, object[] Value)
        {
            if (String.IsNullOrEmpty(StrWhere)) StrWhere = @" 1=1 ";
            String CurrParaName = CreateParaName(Value);
            switch (CompareType.Trim(' ').ToLower())
            {
                case "notin":
                case "in":
                    StrWhere += logicType + currFieldName + CompareType + " (" + CurrParaName + ")"; break;
                default:
                    StrWhere += logicType + @" 1=1  ";
                    break;
            }
            return this;
        }

        private string CreateParaName(object[] Value)
        {
            String TempAllParaName = String.Empty;
            String TempParaName;
            int i = PreWhere.Count;
            foreach (object o in Value)
            {
                TempParaName = "@" + PropertyName + "_P" + i.ToString();
                TempAllParaName += TempParaName + ",";
                if (o == null || String.IsNullOrEmpty(o.ToString()))
                    PreWhere.Add(TempParaName, DBNull.Value);
                else
                    PreWhere.Add(TempParaName, o.ToString());
                i++;
            }
            return TempAllParaName.TrimEnd(',');
        }
    }
}
